package org.ns.tomdog.config;

import org.ns.tomdog.classloader.CommonClassLoader;
import org.ns.tomdog.config.error.ServerConfigParseException;
import org.ns.tomdog.server.*;
import org.ns.tomdog.server.support.ContainerStartup;
import org.ns.tomdog.server.support.ServerStartup;
import org.ns.tomdog.server.support.WebAppContainerStartup;
import org.ns.tomdog.server.support.WebAppContextStartup;

import java.io.File;
import java.util.List;

// conf/server.xml
public class ServerConfig extends XmlConfigParse{

    private ServerStartup serverStartup;
    private String serverPath;
    private CommonClassLoader classLoader;
    public ServerConfig(String serverPath, File serverConfigPath, CommonClassLoader classLoader) throws ServerConfigParseException {
        super(serverConfigPath, classLoader);
        if (!serverPath.endsWith(File.separator)) {
                serverPath = serverPath + File.separator;
        }
        this.serverPath = serverPath;
        this.classLoader = classLoader;
    }

    @Override
    public void parse() {
        ServerStartup serverStartup = new ServerStartup();
        // 解析connector
        Connector connector =
        parseFrist("connector", null, (connectorNode)-> {
            try {
                String protocol = getAttribute(connectorNode, "protocol", "org.ns.tomdog.server.nioprotocol.NioProtocolHandler");
                String maxThread = getAttribute(connectorNode, "maxThread", "60");
                String maxConnection = getAttribute(connectorNode, "maxConnection", "1000");
                String port = getAttribute(connectorNode, "port", "8080");
                Class<ProtocolHandler> protocolClass = getClass(protocol, ProtocolHandler.class);
                ProtocolHandler protocolHandler = protocolClass.newInstance();
                ConnectorConfig config = new ConnectorConfig();
                config.setMaxConnection(Integer.parseInt(maxConnection));
                config.setMaxThread(Integer.parseInt(maxThread));
                config.setPort(Integer.parseInt(port));
                return new Connector(config, protocolHandler, serverStartup);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        });
        serverStartup.setConnector(connector);

        Container container =
        parseFrist("container", null, (containerNode)-> {
           try {
               List<WebAppContainer> webAppContainers =  parseToList(
                       "webapp", containerNode, (webappNode)-> {
                    String host = webappNode.getAttribute("name");
                    String basePath = formatPath(webappNode.getAttribute("basePath"));
                    if (host == null || host.isEmpty() || basePath == null) {
                       return null;
                    }
                    // 解析节点的配置
                    List<WebAppContext> webAppContexts = parseToList(
                            "context", webappNode, (contextNode)->{
                                String docPath = getAttribute(contextNode, "docPath", "ROOT/");
                                String contextPath = getAttribute(contextNode, "path", "/");
                                WebAppContext webAppContext = new WebAppContextStartup(basePath, docPath, contextPath, classLoader);
                                return webAppContext;
                       }
                    );

                    WebAppContainer webAppContainer = new WebAppContainerStartup(host, basePath, webAppContexts);
                    return webAppContainer;
               });
               String defaultHost = getAttribute(containerNode, "defaultHost", "localhost");
               return new ContainerStartup(webAppContainers, defaultHost);
           } catch (Exception e) {
               e.printStackTrace();
               return null;
           }
        });
        serverStartup.setContainer(container);
        this.serverStartup = serverStartup;
    }

    public ServerStartup getServerStartup() {
        return serverStartup;
    }

    private String formatPath(String path) {
        if (path == null) {
            return null;
        }
        if (path.startsWith("/")) {
            return path;
        }
        if (path.length() > 0 && !path.endsWith("/")) {
            path = path + "/";
        }
        return serverPath + path; // /serverPath/path/
    }
}
